package com.antdsp.web.rest.sys;

import com.antdsp.dao.jpa.system.TagDefJpa;
import com.antdsp.data.entity.system.SystemTagDef;
import com.antdsp.utils.Node;
import com.antdsp.utils.TreeBuilder;
import com.antdsp.web.dto.TagTree;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/system/tag")
public class SystemTagDefApi {

    @Autowired
    private TagDefJpa tagDefJpa;

    @GetMapping
    public TagTree list() {
        TagTree root = new TagTree();
        root.setTagId(0L);
        root.setTagName("ceam");

        List<SystemTagDef> list = this.tagDefJpa.findAll();
        long l1 = System.currentTimeMillis();
        buildTree(list);
        long l2 = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>1="+(l2-l1));

        buildTree2(list);
        long l3 = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>2="+(l3-l2));

        this.child(root, list);
        long l4 = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>3="+(l4-l3));
        return root;
    }

    @GetMapping("/o")
    public List<TagTree> getMenuTree() {
        List<SystemTagDef> allMenus = this.tagDefJpa.findAll();
        return TagTree.buildTree(allMenus, "0");
    }

    @GetMapping("/d")
    public List<Node<SystemTagDef>> getNodeTag() {
        List<SystemTagDef> allMenu = this.tagDefJpa.findAll();
        return TreeBuilder.<SystemTagDef>create("0").parse(allMenu, SystemTagDef::getTagId, SystemTagDef::getParentId);
    }

    private void child(TagTree root, List<SystemTagDef> allTags) {
        // 从allTags中取出对应子标签
        List<SystemTagDef> childs = allTags.stream().filter(item ->
                root.getTagId().equals(item.getParentId())).collect(Collectors.toList());
        allTags.removeAll(childs);

        // 注意forEach本身就是有终止条件的，即遍历到最后一个元素
        childs.forEach(item -> {
            TagTree tag = new TagTree();
            tag.setTagId(item.getTagId());
            tag.setTagName(item.getTagName());
            tag.setParentId(item.getParentId());
            // 递归调用
            this.child(tag , allTags);

            root.appendChildren(tag);
        });
    }


    private List<SystemTagDefVO> buildTree(List<SystemTagDef> list) {
        List<SystemTagDefVO> systemTagDefVOList = new ArrayList<>();
        list.forEach(item -> {
            SystemTagDefVO systemTagDefVO = new SystemTagDefVO();
            systemTagDefVO.setTagId(item.getTagId());
            systemTagDefVO.setParentId(item.getParentId());
            systemTagDefVO.setTagName(item.getTagName());
            systemTagDefVOList.add(systemTagDefVO);
        });
        // 取出所有一级的
        List<SystemTagDefVO> collect = systemTagDefVOList.stream()
                .filter(item -> item.getParentId().toString().contains("0"))
                .collect(Collectors.toList());
        systemTagDefVOList.removeAll(collect);
        // 为一级添加二级
        collect.forEach(item -> {
            item.setList(getToo(systemTagDefVOList, item.getTagId().toString()));
            systemTagDefVOList.removeAll(item.getList());
            // 为二级添加三级
            item.getList().forEach(too -> {
                // 移除一级，移除部分二级，最好移除所有二级
                too.setList(getToo(systemTagDefVOList, too.getTagId().toString()));
                // 为三级添加四级
                systemTagDefVOList.removeAll(too.getList());
                too.getList().forEach(three -> {
                    three.setList(getToo(systemTagDefVOList, three.getTagId().toString()));
                    systemTagDefVOList.removeAll(three.getList());
                });
            });
        });
        return collect;
    }

    private List<SystemTagDefVO> buildTree2(List<SystemTagDef> list) {
        List<SystemTagDefVO> systemTagDefVOS = new ArrayList<>();
        list.forEach(item -> {
            SystemTagDefVO systemTagDefVO = new SystemTagDefVO();
            systemTagDefVO.setTagId(item.getTagId());
            systemTagDefVO.setParentId(item.getParentId());
            systemTagDefVO.setTagName(item.getTagName());
            systemTagDefVO.setLevel(item.getLevel());
            systemTagDefVOS.add(systemTagDefVO);
        });

        // 取出所有1级的
        List<SystemTagDefVO> collect = systemTagDefVOS.stream()
                .filter(item -> item.getParentId().toString().contains("0"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(collect);
        // 取出所有2级的，数据库添加了level等级字段牺牲了空间换取时间
        List<SystemTagDefVO> c2 = systemTagDefVOS.stream()
                .filter(item -> item.getLevel().toString().contains("2"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(c2);
        // 取出所有3级的
        List<SystemTagDefVO> c3 = systemTagDefVOS.stream()
                .filter(item -> item.getLevel().toString().contains("3"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(c3);
        // 取出所有4级的
        List<SystemTagDefVO> c4 = systemTagDefVOS.stream()
                .filter(item -> item.getLevel().toString().contains("4"))
                .collect(Collectors.toList());

        collect.forEach(item -> {
            item.setList(getToo(c2, item.getTagId().toString()));
            // 移除已经合并的，避免重复计算
            c2.removeAll(item.getList());
            item.getList().forEach(too -> {
                too.setList(getToo(c3, too.getTagId().toString()));
                c3.removeAll(too.getList());
                too.getList().forEach(three -> {
                    three.setList(getToo(c4, three.getTagId().toString()));
                    c4.removeAll(three.getList());
                });
            });
        });
        return collect;
    }

    private List<SystemTagDefVO> getToo(List<SystemTagDefVO> withOutFirstList, String parentId) {
        List<SystemTagDefVO> collect = withOutFirstList.stream()
                .filter(item -> item.getParentId().toString().contains(parentId))
                .collect(Collectors.toList());
        return collect;
    }
}
